//
//  BiuViewController.swift
//  Biubiubiu
//
//  Created by DevWhan on 2019/5/3.
//  Copyright © 2019 DevWhan. All rights reserved.
//

import Cocoa
import FileKit
import EFQRCode
import SwiftyJSON
import SwiftShell
import ObjectMapper

class BiuViewController: NSViewController {
    
    let path: Path
    var server: BiuServer
    var list = [TargetFile]()
    var ip = ""
    var currentTarget: TargetFile?
    var settingVc: SettingController?
    var queryVc: QueryController?
    var filterProjectOfContainString = ".weex.js"
    let targetSize: TargetSize
    
    @IBOutlet weak var searchView: NSSearchField!
    @IBOutlet weak var tableView: NSTableView!
    @IBOutlet weak var imageView: NSImageView!
    @IBOutlet weak var mainLabel: NSTextField!
    @IBOutlet weak var query: NSButton!
    
    deinit {
        print("销毁了")
    }
    
    init(project: Project,size: TargetSize ,ip: String?,filterContainString: String?) {
        self.path = Path(project.path!)
        self.ip = ip ?? ""
        if let f = filterContainString {
            self.filterProjectOfContainString = f
        }
        self.targetSize = size
        server = BiuServer(project: project)
        super.init(nibName: NSNib.Name("BiuViewController"), bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //data
        configList()
        
        //search
        self.searchView.delegate = self
        
        //tableview
        tableView.delegate = self
        tableView.dataSource = self
        
        //server
        if server.server.state != .running {
            print("启动失败")
        }
        //ip
        if self.ip.count == 0 {
            if let ip = getipAddr(){
                self.ip = ip
            }else{
                //获取IP错误
                self.mainLabel.stringValue = "获取IP失败 需去设置页面自定义"
            }
        }
        
        if self.targetSize == .small {
            self.mainLabel.font = NSFont.systemFont(ofSize: 10)
            self.query.title = "q"
            self.query.font = NSFont.systemFont(ofSize: 10)
            var frame = self.query.frame
            frame.size = CGSize(width: 5, height: frame.size.height)
            self.query.frame = frame
        }
        
        
//        do {
//            try runAndPrint("/usr/local/bin/node","")
//        } catch  {
//            print("error")
//            print(error)
//        }
        
//        let result = run("/usr/local/bin/npm","-v").stdout
//        print(result.description)
//
//        let command = runAsync("pwd", path.rawValue).onCompletion { command in
//             be notified when the command is finished.
//        }
//        command.stdout.onOutput { stdout in
            // be notified when the command produces output (only on macOS).
//            print(stdout)
//        }
//        try? runAndPrint(bash: "ls")
//        var context = CustomContext(main)
//        context.env["PATH"] = "/usr/local/bin/wnode"
//        context.currentdirectory = path.rawValue
//
//        do {
//            try context.runAndPrint("/usr/local/bin/wnode","-v")
//        } catch {
//            print("error")
//            print(error)
//        }
        
//        let commond = context.runAsync("/usr/bin","ls").onCompletion { (command) in
//            print("Over")
//            print(command)
//        }
//        commond.stdout.onOutput { stdout in
//            print(stdout)
//        }
//        commond.stderror.onOutput { stream in
//            print("error")
//            print(stream)
//        }
    }
    
    override func viewWillAppear() {
        super.viewWillAppear()
        sortListData()
        tableView.reloadData()
    }
    
    public func configList(){
        let result = listOfPath(self.path)
        if let storeObjectList = getStoreProject() {
            list = result.map{
                let target = TargetFile(url: $0.rawValue)
                if let alreadyP = storeObjectList.filter({ (item) -> Bool in
                    return item.url == target.url
                }).first {
                    
                    target.name = alreadyP.name
                    target.query = alreadyP.query
                    
                }
                return target
            }
            
        }else{
            list = result.map{ TargetFile(url: $0.rawValue)}
        }
        sortListData()
    }
    
    @IBAction func skipClick(_ sender: NSButton) {
        
//        NSString *s = [NSString stringWithFormat:
//            @"tell application \"Terminal\" to do script \"cd %@\"", folderPath];
//
//        NSAppleScript *as = [[NSAppleScript alloc] initWithSource: s];
//        [as executeAndReturnError:nil];

//        let script = NSAppleScript(source: "tell application \"Terminal\" to do script \"cd ~/Desktop\"")
        
//        script?.executeAndReturnError(nil)
        
        let pasteboard = NSPasteboard.general
        
        pasteboard.declareTypes([NSPasteboard.PasteboardType.string], owner: nil)
        let string = "cd \(path.rawValue) \n npm run dev"
        let b = pasteboard.setString(string, forType: NSPasteboard.PasteboardType.string)
        print(b)
        
        let work = NSWorkspace()
        work.launchApplication("Terminal")
        
    }
    @IBAction func settingClick(_ sender: NSButton) {
        settingVc = SettingController(windowNibName: NSNib.Name("SettingController"))
        settingVc?.defaultIP = self.ip
        settingVc?.defaultFilter = self.filterProjectOfContainString
        settingVc?.defaultSize = self.targetSize
        settingVc?.path = self.path
        
        settingVc?.showWindow(self)
        NSApp.activate(ignoringOtherApps: true)
        settingVc?.window?.makeKeyAndOrderFront(self)
    }
    @IBAction func refreshClick(_ sender: NSButton) {
        configList()
        self.tableView.reloadData()
    }
    @IBAction func quitClick(_ sender: NSButton) {
        if let delete = NSApplication.shared.delegate as? AppDelegate {
            delete.popover.close()
            delete.popover.contentViewController = nil
            delete.setupStatusItem()
        }
    }
    @IBAction func queryClick(_ sender: NSButton) {
        if let target = currentTarget {
            queryVc = QueryController(windowNibName: NSNib.Name("QueryController"))
            queryVc?.targetQuery = target
            queryVc?.confirmBlock = {[weak self] (name,query) in
                self?.changeCurrentTarget(name: name, query: query)
                NotificationCenter.default.post(Notification(name: NSNotification.Name(rawValue: Notification_ShowBiuView)))
            }
            
            queryVc?.showWindow(self)
            NSApp.activate(ignoringOtherApps: true)
            queryVc?.window?.makeKeyAndOrderFront(self)
        }
    }
    
    func changeCurrentTarget(name: String,query: String){
        if let target = currentTarget {
            target.name = name
            target.query = query
            self.tapTarget(target: target)
            self.saveProject()
        }
    }
}

extension BiuViewController: NSTableViewDataSource,NSTableViewDelegate {

    func numberOfRows(in tableView: NSTableView) -> Int {
        return list.count
    }
    
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        if let identifier = tableColumn?.identifier {
            if let cell = tableView.makeView(withIdentifier: identifier, owner: self) as? NSTableCellView {
                let target = list[row]
                cell.textField?.stringValue = target.getShowName(replace: self.filterProjectOfContainString)
                if self.targetSize == .small {
                    cell.textField?.font = NSFont.systemFont(ofSize: 10)
                }
                return cell
            }
        }
        return nil
    }
    
    func tableViewSelectionDidChange(_ notification: Notification) {
        let file = list[tableView.selectedRow]
        self.tapTarget(target: file)
    }
    
    func tapTarget(target: TargetFile){
        self.currentTarget = target
        self.mainLabel.stringValue = target.getShowName(replace: self.filterProjectOfContainString)
        showContentQrCode(target: target)
    }
}

//qrcode
extension BiuViewController {
    
    fileprivate func getBaseUrl() -> String {
        do {
            let port = try server.server.port()
            let baseUrl = "http://\(ip):\(port)/\(server.prePath)"
            return baseUrl
        } catch  {
            return ""
        }
    }
    
    fileprivate func showContentQrCode(target: TargetFile){
        var url = getBaseUrl() + "/" + target.getFileQueryString()
        url = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? url
        print(url)
        showContentQrCode(content: url)
    }
    
    fileprivate func showContentQrCode(content: String){
        if let image = EFQRCode.generate(content: content) {
            imageView.image = NSImage(cgImage: image, size: NSSize(width: imageView.frame.width, height: imageView.frame.height))
        }else{
            
        }
    }
    
}


extension BiuViewController {
    public func listOfPath(_ path: Path) -> [Path]{
        let findPath = path.find(searchDepth: 1, condition: { (target) -> Bool in
            return target.fileName == Config.shared.mainDirectory
        })
        if let mainPath = findPath.first {
            return mainPath.children().filter{ $0.fileName.contains(self.filterProjectOfContainString)}
        }
        
        return [Path]()
    }
    
    public func sortListData(){
        self.list = self.list.sorted(by: { (one, two) -> Bool in
            if let oneTime = one.path.modificationDate,let twoTime = two.path.modificationDate {
                return oneTime.compare(twoTime) == ComparisonResult.orderedDescending
            }
            return true
        })
    }
}

extension BiuViewController: NSSearchFieldDelegate {
    func controlTextDidChange(_ obj: Notification) {
        if searchView.stringValue.count == 0 {
            configList()
        }else{
            self.list = self.list.filter({ (item) -> Bool in
                return item.getShowName(replace: self.filterProjectOfContainString).contains(searchView.stringValue)
            })
        }
        self.tableView.reloadData()
    }
}

//save
extension BiuViewController {
  
    func getStoreProject() -> [TargetFile]?{
        if let storeString = UserDefaults.standard.object(forKey: getStoreKey()) as? String {
            return Mapper<TargetFile>().mapArray(JSONString: storeString)
        }
        
        return nil
    }
    
    func getStoreKey() -> String {
        return "storeProjectName" + path.fileName
    }

    func saveProject(){
        if let projectString = self.list.toJSONString() {
            UserDefaults.standard.set(projectString, forKey: getStoreKey())
            UserDefaults.standard.synchronize()
        }
    }
}
